数学作业
Time Limit: 10 Sec Memory Limit: 128 MB
Description
输入文件只有一行为用空格隔开的两个正整数N和M。
Output
输出仅包含一个非负整数,表示Concatenate(1~N) MOD M的值。
12345678910 1000000000
Sample Output
345678910
HINT
1<=N<=10^8 , 1<=M<=10^9
Main idea
给定一个n,m,创造一个数字顺序连接1~n,输出这个数对m取模的值。
Solution
n<=10^18,排除找规律的可能性,立马想到了用矩阵乘法优化DP,令f[i]表示1~i的值,那么:
然后我们只要推出矩阵即可,轻松想到了:
然后分段矩乘得到答案。
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| #include<bits/stdc++.h> using namespace std;
const int ONE=5;
long long n,MOD; long long a[ONE][ONE],b[ONE][ONE]; long long Index;
void Mul(long long a[ONE][ONE],long long b[ONE][ONE],long long ans[ONE][ONE]) { long long jilu[ONE][ONE]; for(int i=1;i<=3;i++) for(int j=1;j<=3;j++) { jilu[i][j]=0; for(int k=1;k<=3;k++) jilu[i][j]=(jilu[i][j] + a[i][k]*b[k][j]%MOD) % MOD; }
for(int i=1;i<=3;i++) for(int j=1;j<=3;j++) ans[i][j]=jilu[i][j]; }
void Matrix(long long a[ONE][ONE],long long b[ONE][ONE],long long t) { while(t) { if(t&1) Mul(a,b,a); Mul(b,b,b); t>>=1; } }
int main() { cin>>n>>MOD; a[1][3]=1;
long long len=1; for(;;) { len*=10; memset(b,0,sizeof(b)); for(int i=1;i<=3;i++) { for(int j=1;j<=i;j++) b[i][j]=1; } b[1][1]=len % MOD;
if(len<=n) Index=len-len/10; else Index=n-len/10+1; Matrix(a,b,Index); if(len>n) break; }
printf("%lld",a[1][1]); }
|